﻿using HPSocket;
using HPSocket.Adapter;
using HPSocket.Base;
using HPSocket.Sdk;
using HPSocket.Ssl;
using HPSocket.Tcp;
using HPSocketClient;
using HPSocketLibrary;
using System.Text;
using System.Windows;

namespace HPSocketServer
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private ITcpServer<string> server;
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            //this.serverIp.Text = System.Net.IPAddress.Any.ToString();
            server = new TcpServer<string>
            {
                SocketBufferSize = 40960,
                DataReceiveAdapter = new TextDataReceiveAdapter(),
                // ssl 证书加载
                // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags
                //VerifyMode = SslVerifyMode.Peer | SslVerifyMode.FailIfNoPeerCert,
                // 单向验证或客户端可选
                //CaPemCertFileOrPath = caPemCertFileOrPath,
                //PemCertFile = pemCertFile,
                //PemKeyFile = pemKeyFile,
                //KeyPassword = keyPassword
            };

            server.OnPrepareListen += OnPrepareListen;//开始监听事件
            server.OnAccept += OnAccept; //连接事件
            server.OnClose += OnClose;   //断开连接事件
            server.OnParseRequestBody += OnParseRequestBody;// 接收数据事件
            server.OnSend += OnSend;// 发送数据事件
            server.OnShutdown += OnShutdown;//服务器关闭事件
            // ssl server 还应该绑定握手事件, 该事件到达说明两端握手成功, OnAccept只能说明连接进入了, 还没握手
            server.OnHandShake += OnHandShake;
            ConsoleHelper.writeLogHandler += (run) =>
            {
                logParagraph.Inlines.Add(run);
                richTextBox.ScrollToEnd();
            };
        }

        private async void StartBtn_Click(object sender, RoutedEventArgs e)
        {
            logParagraph.Inlines.Clear();
            ushort port = (ushort)serverPort.Text.ToInt32();

            server.Address = this.serverIp.Text;// 设置服务端IP
            if (port == 0)
                port = 902;
            server.Port = port;// 设置端口
            server.SendPolicy = SendPolicy.Direct;

            if (StartBtn.Tag.ToInt() == 0)
            {

                if (server.Start())
                {
                    // 启动成功
                    this.StartBtn.Tag = 1;
                    this.StartBtn.Content = "停止监听";
                }
                else
                {
                    // 启动失败
                }
            }
            else
            {

                this.StartBtn.Tag = 0;
                this.StartBtn.Content = "开始监听";
                await server.StopAsync();
            }
        }
        /// <summary>
        /// 开始监听事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="listen"></param>
        /// <returns></returns>
        private HandleResult OnPrepareListen(IServer sender, IntPtr listen)
        {
            ConsoleHelper.Info($"Socket服务端已开启并监听，IP：{sender.Address} 端口：{sender.Port}");
            return HandleResult.Ok;
        }

        /// <summary>
        /// 响应事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="connId"></param>
        /// <param name="client"></param>
        /// <returns></returns>
        private HandleResult OnAccept(IServer sender, IntPtr connId, IntPtr client)
        {
            return HandleResult.Ok;
        }

        /// <summary>
        /// 接收数据事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="connId"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        private HandleResult OnParseRequestBody(ITcpServer sender, IntPtr connId, string obj)
        {
           ConsoleHelper.Info($"接收的数据：{obj}");
            try
            {
                var _sendData = Encoding.UTF8.GetBytes(obj);
                sender.Send(connId, _sendData, _sendData.Length);//返回响应数据
            }
            catch (Exception ex)
            {
                ConsoleHelper.Error(ex.Message);
            }
            return HandleResult.Ok;
        }

        /// <summary>
        /// 发送数据事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="connId"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        private HandleResult OnSend(IServer sender, IntPtr connId, byte[] data)
        {
            try
            {
                ConsoleHelper.Info(string.Format("TCP服务器发送数据到客户端[{0}]{1}:{2};数据内容[长度{3}]：{4}", connId, sender.Address, sender.Port, data.Length, Encoding.UTF8.GetString(data)));
                return HandleResult.Ok;
            }
            catch (Exception)
            {
                return HandleResult.Ignore;
            }
        }

        /// <summary>
        /// 关闭连接事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="connId"></param>
        /// <param name="socketOperation"></param>
        /// <param name="errorCode"></param>
        /// <returns></returns>
        private HandleResult OnClose(IServer sender, IntPtr connId, SocketOperation socketOperation, int errorCode)
        {
            string _errorMsg = "";
            switch (errorCode)
            {
                case 0:
                    {
                        _errorMsg = "客户端主动断开";
                    }
                    break;
                case 10054:
                    {
                        _errorMsg = "客户端异常断开";
                    }
                    break;
            }
            var _item = StatusManage.SocketClientList.Where(r => r.ConnId == connId).FirstOrDefault();
            if (_item != null)
            {
                lock (StatusManage.SocketClientList)
                {
                    if (StatusManage.SocketClientList.Remove(_item))
                    {
                        ConsoleHelper.Info($"SocketClientList成功移除connId：{connId}");
                    }
                    else
                    {
                        ConsoleHelper.Info($"SocketClientList移除失败connId：{connId}");
                    }
                }
                this.Dispatcher.Invoke(() =>
                {
                    this.ComClient.Items.Remove(_item);
                    this.ComClient.Items.Refresh();
                });
            }
            else
            {
                ConsoleHelper.Info($"SocketClientListr找不到connId：{connId}");
            }
            ConsoleHelper.Info($"Socket Client连接断开 connId：{connId} errorCode：{errorCode} {_errorMsg}");
            return HandleResult.Ok;
        }

        /// <summary>
        /// 服务关闭事件
        /// </summary>
        /// <param name="sender"></param>
        /// <returns></returns>
        private HandleResult OnShutdown(IServer sender)
        {
            ConsoleHelper.Info("Socket服务关闭");
            return HandleResult.Ok;
        }
        /// <summary>
        /// SSL 握手成功的事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="connId"></param>
        /// <returns></returns>
        private HandleResult OnHandShake(IServer sender, IntPtr connId)
        {
            // 获取客户端地址
            if (!sender.GetRemoteAddress(connId, out var ip, out var port))
            {
                return HandleResult.Error;
            }
            var _client = new DeviceInfoView
            {
                ConnId = connId,
                Ip = ip,
                Port = port
            };
            lock (StatusManage.SocketClientList)
            {
                StatusManage.SocketClientList.Add(_client);
            }
            this.Dispatcher.Invoke(() =>
            {
                this.ComClient.Items.Add(_client);
                this.ComClient.Items.Refresh();
            });
            ConsoleHelper.Info($"新的Socket Client IP：{ip} 端口：{port} connId：{connId}");

            return HandleResult.Ok;
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {

            if (server.HasStarted)
            {
                MessageBox.Show(@"请先停止服务", @"服务正在运行:", MessageBoxButton.OK, MessageBoxImage.Warning);
                e.Cancel = true;
                return;
            }
            // 停止释放服务器
            server.Dispose();
        }

        private void SendBtn_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                string hostname = this.serverIp.Text;
                int port = int.Parse(this.serverPort.Text);
                string sendMsg = this.txtMsg.Text;  // 
                if (string.IsNullOrEmpty(sendMsg))
                {
                    ConsoleHelper.Error("发送信息不可为空！");
                    return;
                }

                byte[] bytes = System.Text.Encoding.UTF8.GetBytes(sendMsg + "\r\n");
                int length = bytes.Length;

                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.AppendLine(string.Concat("TCPServer服务器广播了内容：“", sendMsg, "”"));

                List<IntPtr> connIds = server.GetAllConnectionIds();
                stringBuilder.AppendLine($"  客户端个数为{connIds.Count}；客户端接收结果如下：");
                foreach (IntPtr connId in connIds)
                {
                    try
                    {
                        if (!server.GetLocalAddress(connId, out string ip, out ushort port1))
                        {
                            stringBuilder.AppendLine(string.Concat($"    客户端[{connId}]", ",接收结果：失败！连接已断开！"));
                            continue;
                        }
                        bool resultData_TCP = server.Send(connId, bytes, length);  // 连接并发送
                        //stringBuilder.AppendLine(string.Concat($"    客户端[{connId}]{ip}:{port1}", ",接收结果：", resultData_TCP, "_", $"[{_HPSocket_TCPServerHelper._server.ErrorCode}]", _HPSocket_TCPServerHelper._server.ErrorMessage));
                    }
                    catch (Exception ex)
                    {
                        stringBuilder.AppendLine(string.Concat($"    客户端[{connId}]", ",接收结果：失败！ 错误信息：", ex.Message));
                    }
                }
                ConsoleHelper.Info(stringBuilder.ToString());
            }
            catch (Exception ex)
            {
                ConsoleHelper.Error("TCPServer服务器广播内容中止！错误信息：" + ex.Message);
            }
        }
    }
}